﻿// Spun AJAX Framework
// Copyright (C) 2008 Blake Hegerle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spun.Applications;
using System.Net;
using LitJson;
using Spun.Polling;

namespace Spun.Communications.Applications
{
    public class PollingServer : ContextualServer
    {
        public static TimeSpan DEFAULT_TIMEOUT = TimeSpan.FromMinutes(1);

        public PollingServer(ApplicationContextManager ApplicationContextManager)
            : base(ApplicationContextManager)
        { }

        protected override void ProcessRequest(HttpListenerContext Context,
            string RelativePath, ApplicationContext ApplicationContext)
        {
            TimeSpan Timeout;

            try
            {
                var Body = GetRequestBody(Context);
                var Request = JsonMapper.ToObject<Request>(Body);
                Timeout = TimeSpan.Parse(Request.Timeout);
            }
            catch
            {
                Timeout = DEFAULT_TIMEOUT;
            }

            var Poller = new Poller(Context);

            ApplicationContext.PollingPlace.StartPoll(Timeout, Poller);
        }

        private class Request
        {
            public string Timeout { get; set; }
        }

        private class Poller : IPoller
        {
            internal Poller(HttpListenerContext Context) { this.Context = Context; }

            #region IPoller Members

            public void OnTimeout()
            {
                var Response = MakeResponseObject(null);
                ContextualServer.DoResponse(Context, 200, new ResponseObject(Response));
            }

            public void OnUpdatesBecameAvailable(IEnumerable<Update> Updates)
            {
                var Response = MakeResponseObject(Updates);
                ContextualServer.DoResponse(Context, 200, new ResponseObject(Response));
            }

            #endregion

            private class UpdateResponseItem
            {
                public string Path { get; set; }
                public bool Valid { get; set; }
                public object Object { get; set; }
            }

            private object MakeResponseObject(IEnumerable<Update> Updates)
            {
                if (Updates == null)
                {
                    return new { Updates = null as object };
                }
                else
                {
                    var UpdateResponses = from U in Updates
                                          select new UpdateResponseItem
                                          {
                                              Path = U.Path.ToString(),
                                              Valid = U.Valid,
                                              Object = U.Object
                                          };

                    return new
                    {
                        Updates = new List<UpdateResponseItem>(UpdateResponses).ToArray()
                    };
                }
            }

            public HttpListenerContext Context;
        }
    }
}
